﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using AyuBookmark.Common.Interfaces;
using AyuBookmark.Common.Models;
using AyuBookmark.Common.Extensions;
using System.Linq.Expressions;

namespace AyuBookmark.Service.Services
{
    /// <summary>
    /// 书签核心服务实现
    /// </summary>
    public class BookmarkService : IBookmarkService
    {
        private readonly IBookmarkRepository _bookmarkRepository;
        private readonly ICategoryRepository _categoryRepository;
        private readonly IImageRepository _imageRepository;
        private readonly IConfigRepository _configRepository;

        /// <summary>
        /// 初始化书签服务
        /// </summary>
        public BookmarkService(
            IBookmarkRepository bookmarkRepository,
            ICategoryRepository categoryRepository,
            IImageRepository imageRepository,
            IConfigRepository configRepository)
        {
            _bookmarkRepository = bookmarkRepository ?? throw new ArgumentNullException(nameof(bookmarkRepository));
            _categoryRepository = categoryRepository ?? throw new ArgumentNullException(nameof(categoryRepository));
            _imageRepository = imageRepository ?? throw new ArgumentNullException(nameof(imageRepository));
            _configRepository = configRepository ?? throw new ArgumentNullException(nameof(configRepository));
        }

        public async Task<Bookmark> GetBookmarkByUrlAsync(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
            {
                throw new ArgumentException("URL cannot be empty", nameof(url));
            }

            // 通过BookmarkRepository的GetByUrlAsync方法获取书签
            return await _bookmarkRepository.GetByUrlAsync(url);
        }

        //public async Task<Bookmark> GetBookmarkByUrlAsync(string url)
        //{
        //    if (string.IsNullOrWhiteSpace(url))
        //    {
        //        throw new ArgumentException("URL cannot be empty", nameof(url));
        //    }

        //    // 通过BookmarkRepository的GetByUrlAsync方法获取书签
        //    return await _bookmarkRepository.GetByUrlAsync(url);
        //}

        #region 书签核心操作
        /// <inheritdoc />
        public async Task<Bookmark> AddBookmarkAsync(Bookmark bookmark)
        {
            ValidateBookmark(bookmark);

            // 设置默认分类
            if (bookmark.CategoryId == null)
            {
                bookmark.CategoryId = await GetDefaultCategoryIdAsync();
            }

            // 处理首图
            //if (!string.IsNullOrEmpty(bookmark.ImagePath))
            //{
            //    using var imageStream = File.OpenRead(bookmark.ImagePath);
            //    bookmark.ImageId = await _imageRepository.SaveImageFileAsync(
            //        imageStream,
            //        Path.GetExtension(bookmark.ImagePath));
            //}

            if (!string.IsNullOrEmpty(bookmark.ImagePath))
            {
                using var imageStream = File.OpenRead(bookmark.ImagePath);
                var imagePath = await _imageRepository.SaveImageFileAsync(
                    imageStream,
                    Path.GetExtension(bookmark.ImagePath));

                // 获取保存后的图片ID
                var image = await _imageRepository.GetByPathAsync(imagePath);
                bookmark.ImageId = image?.Id;
            }

            // 更新分类使用计数
            if (bookmark.CategoryId.HasValue)
            {
                await UpdateCategoryUsageAsync(bookmark.CategoryId.Value);
            }

            return await _bookmarkRepository.AddAsync(bookmark);
        }

        /// <inheritdoc />
        public async Task<Bookmark> UpdateBookmarkAsync(Bookmark bookmark)
        {
            ValidateBookmark(bookmark);

            var existing = await _bookmarkRepository.GetByIdAsync(bookmark.Id);
            if (existing == null)
            {
                throw new KeyNotFoundException($"Bookmark with ID {bookmark.Id} not found");
            }

            // 处理分类变更
            if (existing.CategoryId != bookmark.CategoryId && bookmark.CategoryId.HasValue)
            {
                await UpdateCategoryUsageAsync(bookmark.CategoryId.Value);
            }

            // 处理图片更新
            //if (bookmark.ImagePath != existing.ImagePath && !string.IsNullOrEmpty(bookmark.ImagePath))
            //{
            //    using var imageStream = File.OpenRead(bookmark.ImagePath);
            //    bookmark.ImageId = await _imageRepository.SaveImageFileAsync(
            //        imageStream,
            //        Path.GetExtension(bookmark.ImagePath));
            //}
            if (bookmark.ImagePath != existing.ImagePath && !string.IsNullOrEmpty(bookmark.ImagePath))
            {
                using var imageStream = File.OpenRead(bookmark.ImagePath);
                var imagePath = await _imageRepository.SaveImageFileAsync(
                    imageStream,
                    Path.GetExtension(bookmark.ImagePath));

                var image = await _imageRepository.GetByPathAsync(imagePath);
                bookmark.ImageId = image?.Id;
            }
            else
            {
                bookmark.ImageId = existing.ImageId;
            }

            return await _bookmarkRepository.UpdateAsync(bookmark) ? bookmark : null;
        }

        /// <inheritdoc />
        public async Task<bool> DeleteBookmarkAsync(int id)
        {
            var bookmark = await _bookmarkRepository.GetByIdAsync(id);
            if (bookmark == null) return false;

            // 不实际删除图片，留待清理任务处理
            return await _bookmarkRepository.DeleteAsync(bookmark);
        }

        /// <inheritdoc />
        public async Task<PaginatedResult<Bookmark>> GetBookmarksAsync(
            int pageIndex = 1,
            int pageSize = 20,
            string searchTerm = null,
            int? categoryId = null)
        {
            Expression<Func<Bookmark, bool>> predicate = b =>
                (string.IsNullOrEmpty(searchTerm) || b.Title.Contains(searchTerm) || b.Description.Contains(searchTerm)) &&
                (!categoryId.HasValue || b.CategoryId == categoryId);

            return await _bookmarkRepository.GetPagedAsync(
                predicate,
                pageIndex,
                pageSize,
                b => b.CreatedTime,
                true);
        }

        /// <inheritdoc />
        public async Task<Bookmark> GetBookmarkDetailsAsync(int id)
        {
            return await _bookmarkRepository.GetByIdAsync(id);
        }

        /// <inheritdoc />
        public async Task<int> ImportBookmarksAsync(IEnumerable<Bookmark> bookmarks)
        {
            int count = 0;
            foreach (var bookmark in bookmarks)
            {
                try
                {
                    await AddBookmarkAsync(bookmark);
                    count++;
                }
                catch
                {
                    // 记录日志但继续导入其他书签
                    continue;
                }
            }
            return count;
        }
        #endregion

        #region 批量操作
        /// <inheritdoc />
        public async Task<int> UpdateBookmarksCategoryAsync(IEnumerable<int> bookmarkIds, int categoryId)
        {
            // 验证分类存在
            var category = await _categoryRepository.GetByIdAsync(categoryId);
            if (category == null)
            {
                throw new KeyNotFoundException($"Category with ID {categoryId} not found");
            }

            // 更新分类使用计数
            await UpdateCategoryUsageAsync(categoryId);

            return await _bookmarkRepository.UpdateCategoryAsync(bookmarkIds, categoryId);
        }

        /// <inheritdoc />
        public async Task<int> DeleteBookmarksAsync(IEnumerable<int> bookmarkIds)
        {
            int count = 0;
            foreach (var id in bookmarkIds)
            {
                if (await DeleteBookmarkAsync(id))
                {
                    count++;
                }
            }
            return count;
        }
        #endregion

        #region 实用方法
        private async Task<int> GetDefaultCategoryIdAsync()
        {
            var defaultCategoryName = await _configRepository.GetConfigValueAsync("DefaultCategory", "未分类");
            var categories = await _categoryRepository.FindAsync(c => c.Name == defaultCategoryName);
            var category = categories.FirstOrDefault();

            if (category == null)
            {
                category = await _categoryRepository.AddAsync(new Category
                {
                    Name = defaultCategoryName,
                    Color = "#CCCCCC"
                });
            }

            return category.Id;
        }

        private async Task UpdateCategoryUsageAsync(int categoryId)
        {
            var category = await _categoryRepository.GetByIdAsync(categoryId);
            if (category != null)
            {
                category.UsageCount++;
                category.LastUsed = DateTime.Now;
                await _categoryRepository.UpdateAsync(category);
            }
        }

        private void ValidateBookmark(Bookmark bookmark)
        {
            if (bookmark == null)
            {
                throw new ArgumentNullException(nameof(bookmark));
            }

            if (string.IsNullOrWhiteSpace(bookmark.Title))
            {
                throw new ArgumentException("Bookmark title cannot be empty");
            }

            if (string.IsNullOrWhiteSpace(bookmark.Url) || !Uri.IsWellFormedUriString(bookmark.Url, UriKind.Absolute))
            {
                throw new ArgumentException("Invalid URL format");
            }
        }
        #endregion
    }
}